package com.gitee.zycra.future.job.service;

import com.gitee.zycra.future.job.common.bo.CommonResult;
import com.gitee.zycra.future.job.common.model.JobSchedule;
import com.gitee.zycra.future.job.common.param.UpdateDependenceParam;
import com.gitee.zycra.future.job.manager.JobDependenceManager;
import com.gitee.zycra.future.job.manager.JobScheduleManager;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import java.util.List;

/**
 * @author zycra
 */
@Slf4j
@Service
public class JobDependenceService {

    @Autowired
    private JobDependenceManager jobDependenceManager;

    @Autowired
    private JobScheduleManager jobScheduleManager;

    /**
     * 更新依赖任务
     *
     * @param updateDependenceParam 更新参数
     * @return 更新结果
     */
    @Transactional(rollbackFor = Exception.class)
    public CommonResult<String> updateJobDependence(UpdateDependenceParam updateDependenceParam) {
        List<Long> parentScheduleIdList = updateDependenceParam.getParentScheduleIdList();
        if (CollectionUtils.isEmpty(parentScheduleIdList)) {
            log.info("父调度信息为空, 删除依赖, updateDependenceParam={}", updateDependenceParam);
        }
        if (parentScheduleIdList.contains(updateDependenceParam.getChildScheduleId())) {
            log.warn("不能依赖自身调度信息, updateDependenceParam={}", updateDependenceParam);
            return CommonResult.failed("不能依赖自身调度信息");
        }
        Integer parentCount = jobScheduleManager.countByIdList(parentScheduleIdList);
        JobSchedule child = jobScheduleManager.selectById(updateDependenceParam.getChildScheduleId());
        if (child == null || parentCount != parentScheduleIdList.size()) {
            log.warn("未查询到任务信息或执行周期不符, updateDependenceParam={}", updateDependenceParam);
            return CommonResult.failed("未查询到任务信息或执行周期不符");
        }
        for (Long parentScheduleId : parentScheduleIdList) {
            if (checkCycleDependence(parentScheduleId, updateDependenceParam.getChildScheduleId())) {
                log.warn("存在循环依赖, updateDependenceParam={}", updateDependenceParam);
                return CommonResult.failed("存在循环依赖");
            }
        }
        jobDependenceManager.deleteChildDependence(updateDependenceParam.getChildScheduleId());
        jobDependenceManager.batchInsertJobDependence(updateDependenceParam);
        return CommonResult.success("修改成功", null);
    }

    /**
     * 检查循环依赖
     *
     * @param parentScheduleId 父调度信息ID
     * @param childId          子调度信息ID
     * @return 父任务名称
     */
    private boolean checkCycleDependence(Long parentScheduleId, Long childId) {
        List<Long> parentList = jobDependenceManager.selectParentIdByChildScheduleId(parentScheduleId);
        while (!CollectionUtils.isEmpty(parentList)) {
            if (parentList.contains(childId)) {
                return true;
            }
            parentList = jobDependenceManager.selectParentIdByChildScheduleIdList(parentList);
        }
        return false;
    }

    /**
     * 根据子调度信息ID查询父任务ID
     *
     * @param childScheduleId 子调度信息ID
     * @return 查询到的数据
     */
    public List<Long> selectParentIdByChildScheduleId(Long childScheduleId) {
        return jobDependenceManager.selectParentIdByChildScheduleId(childScheduleId);
    }
}
